/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * Cryptographic Device Base Class
 *      Provides a base class definition for implementing algorithm-specific 
 * encryption and decryption classes.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.IO;
using System.Threading;

namespace Adaptive.Foundation.Security
{
    /// <summary>
    /// Provides a base class definition for implementing algorithm-specific 
    /// encryption and decryption classes.
    /// </summary>
    public abstract class CryptographicDeviceBase : DisposableObjectBase
    {
        /*--------------------------------------------------------------------------------
         * Public Event Definitions
         *------------------------------------------------------------------------------*/
        #region Public Event Definitions
        /// <summary>
        /// Occurs when an encryption failure is encountered.
        /// </summary>
        public event EventHandler EncryptionFailure;
        /// <summary>
        /// Occurs when a decryption failure is encountered.
        /// </summary>
        public event EventHandler DecryptionFailure;
        /// <summary>
        /// Occurs when a key must be requested from a caller.
        /// </summary>
        public event KeyRequestEventHandler KeyRequest;
        /// <summary>
        /// Occurs when an operation starts.
        /// </summary>
        public event EventHandler OperationStart;
        /// <summary>
        /// Occurs when an operation is updating its current status.
        /// </summary>
        public event ProgressEventHandler OperationUpdate;
        /// <summary>
        /// Occurs when an operation completes.
        /// </summary>
        public event EventHandler OperationComplete;
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// Last operation that was performed.
        /// </summary>
        private CryptographicOperation _lastOperation;
        /// <summary>
        /// Algorithm supported by the child class implementation.
        /// </summary>
        private CryptographicAlgorithm _supportedType = CryptographicAlgorithm.None;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        protected CryptographicDeviceBase()
            : base()
        {
            SetAlgorithmType();
        }
        /// <summary>
        /// Deallocates internally allocated objects.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if ((!Disposed) && (disposing))
            {
                if (_lastOperation != null)
                    _lastOperation.Dispose();
            }
            _lastOperation = null;
            base.Dispose(disposing);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets the algorithm implemented by the child class.
        /// </summary>
        /// <value>
        /// A <see cref="CryptographicAlgorithm"/> enumerated value indicating the 
        /// cryptographic algorithm that is in use.
        /// </value>
        public CryptographicAlgorithm Algorithm
        {
            get { return _supportedType; }
            protected set { _supportedType = value; }
        }
        /// <summary>
        /// Gets a value indicating whether the current instance can perform encryption operations.
        /// </summary>
        /// <value>
        /// <b>true</b> if the object is in a valid state and encryption may be performed; otherwise, <b>false</b>.
        /// </value>
        public abstract bool CanEncrypt { get;}
        /// <summary>
        /// Gets a value indicating whether the current instance can perform decryption operations.
        /// </summary>
        /// <value>
        /// <b>true</b> if the object is in a valid state and decryption may be performed; otherwise, <b>false</b>.
        /// </value>
        public abstract bool CanDecrypt { get;}
        #endregion

        /*--------------------------------------------------------------------------------
         * Protected Methods / Event Methods
         *------------------------------------------------------------------------------*/
        #region Protected Methods / Event Methods
        /// <summary>
        /// Sets the internal value indicating the type of algorithm that is supported.
        /// </summary>
        protected abstract void SetAlgorithmType();
        /// <summary>
        /// Raises the <see cref="EncryptionFailure"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnEncryptionFailure(EventArgs e)
        {
            if (EncryptionFailure != null)
                EncryptionFailure(this, e);
        }
        /// <summary>
        /// Raises the <see cref="DecryptionFailure"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnDecryptionFailure(EventArgs e)
        {
            if (DecryptionFailure != null)
                DecryptionFailure(this, e);
        }
        /// <summary>
        /// Raises the <see cref="KeyRequest"/> event.
        /// </summary>
        /// <param name="e">
        /// A <see cref="KeyRequestEventArgs"/> event arguments instance 
        /// containing the information for the key request.
        /// </param>
        protected virtual void OnKeyRequest(KeyRequestEventArgs e)
        {
            if (KeyRequest != null)
                KeyRequest(this, e);
        }
        /// <summary>
        /// Raises the <see cref="OperationStart"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnOperationStart(EventArgs e)
        {
            if (OperationStart != null)
                OperationStart(this, e);
        }
        /// <summary>
        /// Raises the <see cref="EncryptionFailure"/> event.
        /// </summary>
        /// <param name="e">
        /// A <see cref="ProgressEventArgs"/> event arguments instance 
        /// containg the current operation's status information.
        /// </param>
        protected virtual void OnOperationUpdate(ProgressEventArgs e)
        {
            if (OperationUpdate != null)
                OperationUpdate(this, e);
        }
        /// <summary>
        /// Raises the <see cref="OperationComplete"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnOperationComplete(EventArgs e)
        {
            if (OperationComplete != null)
                OperationComplete(this, e);
        }
        /// <summary>
        /// Sets the current status of the operation and raises the related event.
        /// </summary>
        /// <param name="message">The message to return to a display or log.</param>
        /// <param name="percentComplete">The current percentage completion value.</param>
        protected void SetCurrentStatus(string message, int percentComplete)
        {
            ProgressEventArgs evArgs = null;                //Event arguments.

            evArgs = new ProgressEventArgs(message, percentComplete);
            OnOperationUpdate(evArgs);
            evArgs = null;
        }
        /// <summary>
        /// Performs encryption tasks.
        /// </summary>
        /// <param name="operation">
        /// A <see cref="CryptographicOperation"/> instance specifying how a task is
        /// to be performed.
        /// </param>
        /// <returns>
        /// <b>true</b> if the operation is successful; otherwise, returns <b>false</b>.
        /// </returns>
        protected abstract bool DoEncrypt(CryptographicOperation operation);
        /// <summary>
        /// Performs decryption tasks.
        /// </summary>
        /// <param name="operation">
        /// A <see cref="CryptographicOperation"/> instance specifying how a task is
        /// to be performed.
        /// </param>
        /// <returns>
        /// <b>true</b> if the operation is successful; otherwise, returns <b>false</b>.
        /// </returns>
        protected abstract bool DoDecrypt(CryptographicOperation operation);
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Public Methods / Functions
        /// <summary>
        /// Clears the contents of the object instance without disposing of the instance.
        /// </summary>
        public virtual void Clear()
        {
            if (_lastOperation != null)
                _lastOperation.Clear();
        }
        /// <summary>
        /// Performs the operation as specified in the <i>operation</i> parameter.
        /// </summary>
        /// <param name="operation">
        /// A <see cref="CryptographicOperation"/> instance indicating the operation to 
        /// be performed.
        /// </param>
        /// <returns>
        /// <b>true</b> if the operation is successful; otherwise, returns <b>false</b>.
        /// </returns>
        public virtual bool PerformOperation(CryptographicOperation operation)
        {
            bool returnValue = false;                           //Return value.

            if (operation.Algorithm != _supportedType)
                throw new InvalidAlgorithmException();
            else
            {
                try
                {
                    if (operation.OperationType == CryptographicOperationType.Encrypt)
                        returnValue = DoEncrypt(operation);
                    else

                        returnValue = DoDecrypt(operation);

                }
                catch (Exception ex)
                {
                    returnValue = false;
                    operation.Result.Success = false;
                    operation.Result.ResultType = CryptographicResultType.UnknownException;
                    operation.Result.LastException = ex;
                }
            }

            return returnValue;
        }
        #endregion

    }
}
